package com.easylinkin.linkappapi.machinery.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.config.entity.Config;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.device.mapper.DeviceMapper;
import com.easylinkin.linkappapi.deviceunit.service.DeviceUnitService;
import com.easylinkin.linkappapi.iaqi.config.IaqiConfigUtil;
import com.easylinkin.linkappapi.machinery.dto.DeviceMachineryDto;
import com.easylinkin.linkappapi.machinery.dto.MachineryRecordDTO;
import com.easylinkin.linkappapi.machinery.dto.MachineryUserLinkDTO;
import com.easylinkin.linkappapi.machinery.entity.MachineryDeviceRef;
import com.easylinkin.linkappapi.machinery.entity.MachineryParameter;
import com.easylinkin.linkappapi.machinery.entity.MachineryRecord;
import com.easylinkin.linkappapi.machinery.entity.MachineryType;
import com.easylinkin.linkappapi.machinery.mapper.*;
import com.easylinkin.linkappapi.machinery.service.MachineryRecordService;
import com.easylinkin.linkappapi.machinery.vo.MachineryDeviceVo;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.sevice.LinkappTenantService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 闸机表 服务实现类
 * </p>
 *
 * @author TongJie
 * @since 2022-04-13
 */
@Service
public class MachineryRecordServiceImpl extends ServiceImpl<MachineryRecordMapper, MachineryRecord> implements
        MachineryRecordService {

    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;

    @Autowired
    private MachineryParameterMapper machineryParameterMapper;

    @Autowired
    private MachineryUserLinkMapper machineryUserLinkMapper;

    @Autowired
    private MachineryTypeMapper machineryTypeMapper;

    private final static String machineryTypeRefConfigStartKey = "MACHINERY_TYPE_";

    @Resource
    private IaqiConfigUtil iaqiConfigUtil;

    @Resource
    private DeviceMapper deviceMapper;

    @Resource
    private MachineryDeviceRefMapper machineryDeviceRefMapper;

    /**
     * 增加
     *
     * @param machineryRecordDTO
     */
    @Override
    public void insert(MachineryRecordDTO machineryRecordDTO) {
        MachineryRecord machineryRecord = BeanUtil.toBean(machineryRecordDTO, MachineryRecord.class);
        /**
         * 验证重复
         */
        this.checkExist(machineryRecord);
        //设置基本属性
        this.setBase(machineryRecord);
        //处理参数
        List<MachineryParameter> parameterList = machineryRecordDTO
                .getMachineryParameterList();
        if (null != parameterList && parameterList.size() > 0) {
            String s = JSONUtil.parse(parameterList).toString();
            machineryRecord.setParameter(s);
        }
        this.save(machineryRecord);
    }

    /**
     * 根据id编辑
     *
     * @param machineryRecordDTO
     */
    @Override
    public void updateOne(MachineryRecordDTO machineryRecordDTO) {
        MachineryRecord machineryRecord = BeanUtil.toBean(machineryRecordDTO, MachineryRecord.class);
        /**
         * 验证重复
         */
        this.checkExist(machineryRecord);
        //设置基本属性
        this.setBase(machineryRecord);
        //处理参数
        List<MachineryParameter> parameterList = machineryRecordDTO
                .getMachineryParameterList();
        if (null != parameterList && parameterList.size() > 0) {
            String s = JSONUtil.parse(parameterList).toString();
            machineryRecord.setParameter(s);
        }
        this.updateById(machineryRecord);
    }

    /**
     * @Description: 查询设备特性参数
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public List<MachineryParameter> getParameter(String code) {
        LinkappUser curr = linkappUserContextProducer.getCurrent();
        String tenantId = curr!=null?curr.getTenantId():null;
        QueryWrapper<MachineryParameter> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type_code_", code)
                .eq("tenant_id_",tenantId);
        List<MachineryParameter> parameters = machineryParameterMapper.selectList(queryWrapper);
        if(CollectionUtil.isEmpty(parameters)){// 默认查公共的
            QueryWrapper<MachineryParameter> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("type_code_", code).isNull("tenant_id_");
            parameters = machineryParameterMapper.selectList(queryWrapper1);
        }
        return parameters;
    }

    /**
     * @Description: 查询管理人员
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public List<MachineryUserLinkDTO> getUser(String code, String tenantId2) {
        String tenantId = tenantId2;
        tenantId = tenantId == null ? linkappUserContextProducer.getNotNullCurrent().getTenantId() : tenantId;
        List<MachineryUserLinkDTO> machineryUserLinkDTOS = machineryUserLinkMapper.getUser(code, tenantId);
        machineryUserLinkDTOS.forEach(m->{
            //处理name
            if (Integer.valueOf(1).equals(m.getType())){
                String name = m.getTypeName();
                m.setTypeName(name.substring(name.lastIndexOf("/")+1));
            }
        });
        return machineryUserLinkDTOS;
    }

    /**
     * @Description: 根据条件，查询
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public Map<String, List<MachineryRecord>> queryAppList(MachineryRecord machineryRecord) {
        List<MachineryType> types = machineryTypeMapper.selectList(new QueryWrapper<>());
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        QueryWrapper<MachineryRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tenant_id_", tenantId).orderByDesc("modify_time_");
        if (StringUtils.isNotBlank(machineryRecord.getName())) {
            queryWrapper.like("name_", machineryRecord.getName());
        }
        queryWrapper.orderByAsc("type_code_");
        List<MachineryRecord> machineryRecords = baseMapper.selectList(queryWrapper);
        //根据类型分组
        Map<String, List<MachineryRecord>> map = machineryRecords.stream()
                .collect(Collectors.groupingBy(m -> m.getTypeCode()));
        Map<String, List<MachineryRecord>> result = new HashMap<>();
        map.forEach((k, v) -> {
            List<MachineryType> typeList = types.stream().filter(t -> k.equals(t.getCode()))
                    .collect(Collectors.toList());
            result.put(typeList.get(0).getName(), v);
        });
        return result;
    }

    @Override
    public void unbindIotDevice(Collection<Integer> ids) {
        if (CollectionUtil.isNotEmpty(ids)) {
            Date now = DateUtil.date();
            ids.stream().forEach(c -> {
                //这个有点诡异，跟指定逻辑删除字段有关。UpdateWrapper对象set值、eq等过滤条件可同时
                UpdateWrapper<MachineryDeviceRef> updateWrapper = new UpdateWrapper<>();
                updateWrapper.set("delete_state", 0);
                updateWrapper.eq("machinery_id", c);
                MachineryDeviceRef model = new MachineryDeviceRef();
                //model.setDeleteState(0);
                model.setModifyTime(now);
                machineryDeviceRefMapper.update(model, updateWrapper);
            });
        }
    }

    @Override
    public void deleteByMap(Map<String, Object> map) {
        if (map.get("tenant_id")!=null){
            String tenantId = (String) map.get("tenant_id");
            //通过tenantId查所有的机械台账
            List<MachineryRecord> machineryRecords = getByTenantId(tenantId);
            if (CollectionUtil.isNotEmpty(machineryRecords)){
                List<Integer> ids = machineryRecords.stream().map(MachineryRecord::getId).collect(Collectors.toList());
                removeByIds(ids);
                //增加解除IOT设备绑定关系
                unbindIotDevice(ids);
            }
        }

    }

    private List<MachineryRecord> getByTenantId(String tenantId) {
        return this.baseMapper.selectByTenantId(tenantId);
    }


    @Override
    public RestMessage iotDeviceRefData(MachineryDeviceVo machineryDeviceVo) {
        Integer machineryId = machineryDeviceVo.getId();
        Assert.notNull(machineryId, "电子档案设备id为空");

        //MACHINERY_TYPE_QUIP_SJJ_02,MACHINERY_TYPE_QUIP_TSQZJ_01
        //查询电子档案设备信息
        MachineryRecord machineryRecord = this.baseMapper.selectById(machineryId);
        if (machineryRecord == null) {
            return RestBuilders.errorBuilder().message("电子档案信息不存在").build();
        }
        String deviceUnitCodeConfigKey = machineryTypeRefConfigStartKey + "" + machineryRecord.getTypeCode();

        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();

        Config config = iaqiConfigUtil.getOneConfigs(deviceUnitCodeConfigKey, tenantId);
        if (config == null || StringUtils.isBlank(config.getValue())) {
            return RestBuilders.errorBuilder().message("缺少电子档案关联IOT设备配置").build();
        }
        String configVal = config.getValue();
        JSONArray jsonArray = JSONUtil.parseArray(configVal);
        if (CollectionUtil.isEmpty(jsonArray)){
            return RestBuilders.errorBuilder().message("缺少电子档案关联IOT设备配置").build();
        }

        List<String> unitsCodeLs = converConfigToUnitCodeList(jsonArray);
        if (CollectionUtil.isEmpty(unitsCodeLs)){
            return RestBuilders.errorBuilder().message("缺少电子档案关联IOT设备配置").build();
        }

        machineryDeviceVo.setUnitCodeList(unitsCodeLs);
        //查询所有可关联的设备
        machineryDeviceVo.setBinded(0);
        List<DeviceMachineryDto> noBindList = deviceMapper.selectDeviceMachineryDtoList(machineryDeviceVo);

        //已绑定的
        machineryDeviceVo.setBinded(1);
        List<DeviceMachineryDto> yesBindList = deviceMapper.selectDeviceMachineryDtoList(machineryDeviceVo);

        JSONObject json = new JSONObject();
        json.putOpt("noBindList", noBindList);
        json.putOpt("yesBindList", yesBindList);

        return RestBuilders.successBuilder().data(json).build();
    }

    @Override
    public RestMessage bindIotDevices(MachineryDeviceVo machineryDeviceVo) {
        Integer machineryId = machineryDeviceVo.getId();
        Assert.notNull(machineryId, "电子档案设备id为空");

        //查询电子档案信息
        MachineryRecord machineryRecord = this.baseMapper.selectById(machineryId);
        if (machineryRecord == null) {
            return RestBuilders.errorBuilder().message("电子档案信息不存在").build();
        }

        //查询之前绑定IOT设备
        QueryWrapper<MachineryDeviceRef> qw = new QueryWrapper<>();
        qw.eq("machinery_id", machineryId);
        List<MachineryDeviceRef> machineryDeviceRefList = machineryDeviceRefMapper.selectList(qw);
        //先删除上次的绑定
        if (CollectionUtil.isNotEmpty(machineryDeviceRefList)) {
            List<Long> refIds = machineryDeviceRefList.stream().map(e -> e.getId()).collect(Collectors.toList());
            machineryDeviceRefMapper.deleteBatchIds(refIds);
        }
        //重新再绑定
        List<Device> bindDeviceList = machineryDeviceVo.getBindDeviceList();
        if (CollectionUtil.isNotEmpty(bindDeviceList)) {
            bindDeviceList.stream().forEach(c -> {
                MachineryDeviceRef ref = new MachineryDeviceRef();
                ref.setDeviceId(c.getId());
                ref.setMachineryId(machineryId);
                ref.setDeviceCode(c.getCode());
                ref.setMachineryCode(machineryRecord.getCode());
                ref.setCreateTime(DateUtil.date());
                ref.setModifyTime(ref.getCreateTime());
                ref.setDeleteState(1);
                machineryDeviceRefMapper.insert(ref);
            });
        }

        return RestBuilders.successBuilder().build();
    }
    @Autowired
    private LinkappTenantService linkappTenantService;

    @Override
    public IPage<MachineryRecord> queryListByPage(RequestModel<MachineryRecord> requestModel, Boolean enterpriseFlag) {
        Page page = requestModel.getPage();
        MachineryRecord machineryRecord = requestModel.getCustomQueryParams();
        //项目id 过滤
        QueryWrapper<MachineryRecord> queryWrapper = new QueryWrapper<>();
        //查询参数
        if (StringUtils.isNotBlank(machineryRecord.getName())) {
            queryWrapper.like("name_", machineryRecord.getName());
        }
        if (StringUtils.isNotBlank(machineryRecord.getTypeCode())) {
            queryWrapper.like("type_code_", machineryRecord.getTypeCode());
        }
        if (StringUtils.isNotBlank(machineryRecord.getCode())) {
            queryWrapper.like("code_", machineryRecord.getCode());
        }
        if (ObjectUtils.isNotEmpty(machineryRecord.getJoinStartTime())) {
            queryWrapper.ge("join_time_", machineryRecord.getJoinStartTime());
        }
        if (ObjectUtils.isNotEmpty(machineryRecord.getJoinEndTime())) {
            queryWrapper.le("join_time_", machineryRecord.getJoinEndTime());
        }
        if (enterpriseFlag == null || !enterpriseFlag) {
            LinkappUser curr = linkappUserContextProducer.getCurrent();
            if (curr != null) {
                String tenantId = curr.getTenantId();
                queryWrapper.eq("tenant_id_", tenantId);
            }
        }
        if (machineryRecord.getPlatformProjectName() != null && machineryRecord.getPlatformProjectName().length() > 0) {
            List<String> tenantIds = new LambdaQueryChainWrapper<>(linkappTenantService.getBaseMapper()).like(LinkappTenant::getPlatformProjectName, machineryRecord.getPlatformProjectName())
                    .list().stream().map(LinkappTenant::getId).collect(Collectors.toList());
            if (tenantIds.size() > 0) {
                queryWrapper.in("tenant_id_", tenantIds);
            } else {
                return page;
            }
        }
        queryWrapper.orderByDesc("modify_time_");
        IPage<MachineryRecord> machineryRecordIPage = baseMapper.selectPage(page, queryWrapper);
        //查询所有的型号
        List<MachineryType> machineryTypes = machineryTypeMapper.selectList(new QueryWrapper<>());
        machineryRecordIPage.getRecords().forEach(m -> {
            List<MachineryType> types = machineryTypes.stream()
                    .filter(ma -> ma.getCode().equals(m.getTypeCode()))
                    .collect(Collectors.toList());
            if (types.size() > 0) {
                m.setTypeCodeName(types.get(0).getName());
            }
        });
        if (enterpriseFlag != null && enterpriseFlag) {
            Set<String> set = machineryRecordIPage.getRecords().stream().map(MachineryRecord::getTenantId).collect(Collectors.toSet());
            if (set.size() != 0) {
                //查询所有的租户
                new LambdaQueryChainWrapper<>(linkappTenantService.getBaseMapper()).select(LinkappTenant::getId, LinkappTenant::getPlatformProjectName)
                        .in(LinkappTenant::getId, set).list().forEach(tenant -> {
                            machineryRecordIPage.getRecords().forEach(m -> {
                                if (tenant.getId().equals(m.getTenantId())) {
                                    m.setPlatformProjectName(tenant.getPlatformProjectName());
                                }
                            });
                        });
            }

        }

        return machineryRecordIPage;
    }

    /**
     * 验证重复
     */
    private void checkExist(MachineryRecord machineryRecord) {
        QueryWrapper<MachineryRecord> queryWrapper = new QueryWrapper<>();
        //设置判断重复条件
        queryWrapper.eq("code_", machineryRecord.getCode())
                .eq("tenant_id_", linkappUserContextProducer.getNotNullCurrent().getTenantId());
        //编辑的时候存在id
        Optional.ofNullable(machineryRecord.getId()).ifPresent(id -> queryWrapper.ne("id", machineryRecord.getId()));
        Integer integer = baseMapper.selectCount(queryWrapper);
        if (integer > 0) {
            throw new BusinessException("该闸机已存在");
        }
    }

    /**
     * 设置基本属性
     *
     * @param machineryRecord
     */
    private void setBase(MachineryRecord machineryRecord) {
        machineryRecord.setModifyTime(new Date());
        machineryRecord.setModifyId(linkappUserContextProducer.getCurrent().getId());
        //没有id就是新增,有就是编辑
        if (null == machineryRecord.getId()) {
            machineryRecord.setCreatorId(linkappUserContextProducer.getCurrent().getId());
            machineryRecord.setCreateTime(new Date());
            machineryRecord.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        }
    }

    @Autowired
    private DeviceUnitService deviceUnitService;

    /**
     * @param jsonArray
     * @return
     */
    private List<String> converConfigToUnitCodeList(JSONArray jsonArray) {
        List<String> unitTypeNameLs = jsonArray.stream().map(e -> {
            JSONObject jsonObject = (JSONObject) e;
            if (((JSONObject) e).containsKey("unitTypeName")) {
                return jsonObject.getStr("unitTypeName");
            } else {
                return null;
            }
        }).collect(Collectors.toList());
        return deviceUnitService.selectDeviceUnitByDeviceTypeNames(unitTypeNameLs);
    }
}
